/**
 *	---------------------------------------------------------------------------
 *	COMP 6231/FALL 2013
 *	Assignment - 02
 *	@author Talha Rahman (1296884)
 *	---------------------------------------------------------------------------
 *	The OfficerClient class provides the necessary functions for an user (Police Officer)
 *	to interact with the RMI server. It sends RMI requests to the RMI server through the 
 *	StationServerInterface interface.
 *  
 *  Note that this class is RMI based and not used for submission 02. 
 *  The CORBA based {@link OfficerClientCORBA} is used as the officer client application.
 *  
 *	@see {@link StationServerInterface}
 *	  
 */
package ca.concordia.comp6231.client;

import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import ca.concordia.comp6231.server.StationServerInterface;

public class OfficerClient {
	
	private static StationServerInterface server;
	private static Scanner keyboard = new Scanner(System.in);
	private final static Logger logger = Logger.getLogger(OfficerClient.class.getName());

	/**
	 * Function main - loads the officer client application
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		displayWelcome();
		String badgeID = getBadgeID();
		String stationName = extractStationNameFromBadgeID(badgeID);
		if(stationName == null){
			System.out.println("Exiting.....");
			System.exit(-1);
		}
		
		OfficerClientConfiguration config = new OfficerClientConfiguration(stationName);
		String logFileName = "Client_" + badgeID + "_" + System.currentTimeMillis() + ".log";
		initLogging(logFileName);
		
		server = loadServer(config.getServerConnectionString());
		
		int userChoice = 0;
		while(userChoice != 5){
			displayChoices();
			userChoice = getUserChoice();
			performUserChosenActionNo(userChoice);
		}
	}
	
	/**
	 * Display a list of choices to the user
	 */
	private static void displayChoices(){
		System.out.println();
		System.out.println("-----------------------------------------------------");
		System.out.println("You can perform the following functions (1 - 5)");
		System.out.println("1. createCRecord");
		System.out.println("2. createMRecord");
		System.out.println("3. getRecordCounts");
		System.out.println("4. editCRecord");
		System.out.println("5. Exit");
	}
	
	/**
	 * Connect to the server through RMI
	 * @see {@link StationServerInterface}
	 * @param serverConnectionString A string that specifies which server to connect to.
	 * @return An instance of the initiated server interface.
	 */
	private static StationServerInterface loadServer(String serverConnectionString){
		StationServerInterface server = null;
		try{
			System.setSecurityManager(new RMISecurityManager());
			server = (StationServerInterface) Naming.lookup("rmi://" + serverConnectionString);
			String message = "Connected to RMI server: " + serverConnectionString;
			System.out.println(message);
			logger.log(Level.INFO, message);
		}catch(Exception e){
			String message = "Couldn't connect to RMI server: " + serverConnectionString;
			message += "Reason: " + e.getMessage();
			message += "Please try again later. Exiting......";
			System.out.println(message);
			logger.log(Level.SEVERE, message);
			
			System.exit(-1);
		}
		
		return server;
	}
	
	/**
	 * Display a welcome message.
	 */
	private static void displayWelcome(){
		System.out.println("Welcome to Distributed Police Information System (DPIS)");
	}
	
	/**
	 * Gets the badge ID from user input.
	 * @return The badge ID.
	 */
	private static String getBadgeID(){
		System.out.println();
		System.out.print("Please enter your badge ID:");
		
		String userInput = keyboard.next();
		
		return userInput;
	}
	
	/**
	 * Extracts and returns the station name from the badge ID.
	 * @param badgeID The badge ID.
	 * @return The extracted station name (i.e. SPL, SPB, SPVM, etc).
	 */
	private static String extractStationNameFromBadgeID(String badgeID){
		try{
			int i = 0;
			while (!Character.isDigit(badgeID.charAt(i))){
				i++;
			}
			
			return badgeID.substring(0,i);
		}
		catch(Exception e){
			System.out.println("Invalid badge ID:");
			return null;
		}
	}
	
	/**
	 * Initialize a logging object for this client application.
	 * @param fileName
	 */
	private static void initLogging(String fileName){
		FileHandler fh = null;
		try {
			fh = new FileHandler(fileName, false);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		fh.setFormatter(new SimpleFormatter()); 
		logger.setUseParentHandlers(false);
		logger.addHandler(fh);
		
		logger.setLevel(Level.INFO);
	}

	/**
	 * Gets a numeric (integer) keyboard input from user to decide which operation to perform.
	 * @return The numeric (integer) user input.
	 */
	private static int getUserChoice(){
		System.out.println();
		System.out.print("Your choice:");
		
		int userInput = 0;
		
		boolean inputValid = false;
		while(!inputValid){
			try{
				userInput = keyboard.nextInt();
				inputValid = true;
				keyboard.nextLine();
			}catch(Exception e){
				System.out.println("Invalid Input, please enter an Integer");
				inputValid = false;
				keyboard.nextLine();
			}
		}
		
		return userInput;
	}
	
	/**
	 * Performs the chose user action on the server through the {@link StationServerInterface}.
	 * @param userChoice The user choice
	 */
	private static void performUserChosenActionNo(int userChoice){
		switch(userChoice){
			case 1:
				createCRecord();
				break;
			case 2:
				createMRecord();
				break;
			case 3:
				getRecordCounts();
				break;
			case 4:
				editCRecord();
				break;
			case 5:
				System.out.println("Good bye.");
				break;
			default:
				System.out.println("Invalid user action chosen.");
				break;
		}
	}
	
	/**
	 * Creates a Criminal Record on the RMI server by sending a RMI request through the 
	 * {@link StationServerInterface}
	 */
	private static void createCRecord(){
		System.out.println("-----------------------------------------------------");
		System.out.println("createCRecord:");
		System.out.println("Please enter " +
				"first name, last name, description, status (separated by comma) and press enter");
		try {
			String userInput 	= keyboard.next();
			List<String> items 	= Arrays.asList(userInput.split("\\s*,\\s*"));
			String firstName 	= items.get(0);
			String lastName 	= items.get(1);
			String description 	= items.get(2);
			String status 		= items.get(3);
			
			logger.log(Level.INFO, "Attempting to createCRecord with user input: + " + userInput);
		
			String reponse = server.createCRecord(firstName, lastName, description, status);
			logger.log(Level.INFO, "Result of createCRecord attempt: " + reponse);
			System.out.println(reponse);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Error in createCRecord attempt: " + e.getMessage());
			System.out.println("Error couldn't process request.");
			System.out.println("Reason :" + e.getMessage());
		}
	}
	
	/**
	 * Creates a Missing Record on the RMI server by sending a RMI request through the 
	 * {@link StationServerInterface}
	 */
	private static void createMRecord(){
		System.out.println("-----------------------------------------------------");
		System.out.println("createMRecord:");
		System.out.println("Please enter " +
				"first name, last name, description, address, last date, last location, status,  " +
				"(separated by comma) and press enter");
		try {
			String userInput = keyboard.next();
			List<String> items 	= Arrays.asList(userInput.split("\\s*,\\s*"));
			String firstName 	= items.get(0);
			String lastName 	= items.get(1);
			String description 	= items.get(2);
			String address 		= items.get(3);
			String lastDate 	= items.get(4);
			String lastLocation = items.get(5);
			String status 		= items.get(6);
			
			logger.log(Level.INFO, "Attempting to createMRecord with user input: + " + userInput);
		
			String response = server.createMRecord(firstName, lastName, description, address, lastDate, lastLocation, status);
			logger.log(Level.INFO, "Result of createMRecord attempt: + " + response);
			System.out.println(response);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Error in createMRecord attempt: " + e.getMessage());
			System.out.println("Error couldn't process request.");
			System.out.println("Reason :" + e.getMessage());
		}
	}
	
	/**
	 * Gets the record count for all the RMI servers by sending a RMI request through the 
	 * {@link StationServerInterface}
	 */
	private static void getRecordCounts(){
		System.out.println("-----------------------------------------------------");
		System.out.println("getRecordCounts:");
		System.out.println("Retrieving record counts....");
		
		logger.log(Level.INFO, "Attempting to getRecordCounts.");
		
		try {
			String response = server.getRecordCounts();
			logger.log(Level.INFO, "Result of getRecordCounts attempt: " + response);
			System.out.println(response);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Error in getRecordCounts attempt: " + e.getMessage());
			System.out.println("Error couldn't process request.");
			System.out.println("Reason :" + e.getMessage());
		}
	}
	
	/**
	 * Updates a record on the RMI server by sending a RMI request through the 
	 * @see {@linkStationServerInterface}
	 */
	private static void editCRecord(){
		System.out.println("-----------------------------------------------------");
		System.out.println("editCRecord:");
		System.out.println("Please enter " +
				"last name, record id, new status,  " +
				"(separated by comma) and press enter");
		
		String userInput = keyboard.next();
		List<String> items = Arrays.asList(userInput.split("\\s*,\\s*"));
		String lastName    = items.get(0);
		String recordID    = items.get(1);
		String newStatus   = items.get(2);
		
		logger.log(Level.INFO, "Attempting to editCRecord with user input: " + userInput);
		
		try {
			String response = server.editRecord(lastName, recordID, newStatus);
			logger.log(Level.INFO, "Result of editCRecord attempt: + " + response);
			System.out.println(response);
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Error in editCRecord attempt: " + e.getMessage());
			System.out.println("Error couldn't process request.");
			System.out.println("Reason :" + e.getMessage());
		}		
	}
	
	

}
